package org.huang.test;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.IntBinaryOperator;

/**
 * @author hdu_huang
 * @since 2024/1/5 16:39
 */
public class Invoke {
    private String name;
    private int age;
    private final Runnable runnable = () -> System.out.println("Hello");

    private Object[] objects;

    // VarHandle替代Unsafe的变量操作, 生成类[defineClass, defineAnonymousClass]   VarHandle的创建比较耗时(类字段)
    // VarHandle类可以用于访问对象字段, 数组元素和静态字段  [原子性访问]
    // 内存序: total ordering 全局序(串行化) 和 partial ordering部分时序    {A,B,C} A>B>C [TO],  A>C B [PO]
    // MethodHandles   https://www.inlighting.org/archives/lamport-timestamp-vector-clock
    // fullFence   内存序：C++ 6种内存序
    //* https://zhuanlan.zhihu.com/p/133851347  volatile底层原理
    public static void main(String[] args) throws Exception {
        Invoke test = new Invoke();

        VarHandle handle = MethodHandles.lookup().findVarHandle(Invoke.class, "name", String.class);
        handle.set(test, "hello");

        //major  内存屏障(JMM抽象出的指令, 非CPU真实)  X86 只支持fullFence   lock_开头的指令
        // 1.禁止屏障两边指令重排序  2.控制内存读写和缓存失效(可见性)
        // 读屏障 Load Barrier  在读指令**之前**插入读屏障，让缓存失效，读主内存
        // 写屏障 Store Barrier 在写指令**之后**插入写屏障，强制把缓存刷入到主内存      写之后, 读之前
        // Load读指令,  Store写指令   4种排序，总共4种内存屏障
        // Load1;LoadLoad;Load2      读屏障
        // Store1;StoreStore;Store2  写屏障
        // Load1;LoadStore;Store2    无效屏障，仅仅禁止重排序   [读写屏障无效]
        // Store1;StoreLoad;Load2    full屏障           [写读屏障 full]
        // final变量初始化后插入一个写屏障

        //major
        // getOpaque setOpaque 保证其同一变量不重排和可见性，但不使用屏障，  **不阻碍其它变量，volatile会影响所以普通变量**
        // getAcquire(同getVolatile)      LoadLoad-get-LoadStore
        // setRelease(比setVolatile轻量)   LoadStore-set-StoreStore   后面变量的读没有可见性
        // getVolatile    setVolatile 同volatile


        //! ***volatile原理***
        //LoadLoad    volatile读操作  LoadStore(防止重排)       第一个读屏障 1.防止普通写指令重排 2.读内存   第二个屏障防止普通写指令重排
        //StoreStore  volatile写操作  StoreLoad(fullFence)     1.防止普通读写指令重排 2.后面的读具有可见性(happens-before)

        handle.setOpaque(test, "world");
        handle.setRelease(test, "!");
        handle.setVolatile(test, "hec");

        VarHandle.AccessMode getAndSetAcquire = VarHandle.AccessMode.GET_AND_SET_ACQUIRE;

        //内存屏障（Memory Barrier）与内存栅栏（Memory Fence）是同一个概念
        //内存屏障 volatile也是内存屏障实现   load直接读内存  store直接写内存
        //VarHandle.fullFence();      //读写屏障
        VarHandle.acquireFence();   //loadFence(读屏障)
        VarHandle.releaseFence();   //storeFence(写屏障)
        VarHandle.storeStoreFence();//写屏障

        //get/set Opaque Plain  Plain/Release(lazySet)    setVolatile/getVolatile
        AtomicInteger atomicInteger = new AtomicInteger(1);
        //atomicInteger.setPlain();

        Class<?> c = MethodHandles.lookup().findClass("org.huang.test.Feature$B");

        Class<?> c1 = MethodHandles.lookup().lookupClass();
        Class<?> c2 = MethodHandles.lookup().previousLookupClass();



        System.out.println(c2);

        IntBinaryOperator intAdds = (a, b) -> a + b;
        System.out.println(intAdds.applyAsInt(1, 3));

        test.runnable.run();

        VarHandle varHandle = MethodHandles.lookup().findVarHandle(Invoke.class, "objects", Object[].class);

        //访问数组
        VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(Object[].class);

        Object[] objects1 = new Object[32];

        varHandle.set(test, objects1);

        arrayVarHandle.set(test.objects, 1, new Object());
        arrayVarHandle.setVolatile(test.objects, 2, "hello world!");

        Object aVolatile = arrayVarHandle.getVolatile(test.objects, 2);

    }


    public void sayHello(String content) {
        System.out.println(content);
    }
}
